/*
	Generators from libNoise.
	
	This file based on code from "libNoise" project by Jason Bevins http://libnoise.sourceforge.net/
	Released under the terms of the GNU Lesser General Public License.
*/

//------------------------------------------------------------------------------//
//									HEADER										//

#include "base.cl"

// Noise Quality //
#define NOISE_QUALITY_FAST		0
#define NOISE_QUALITY_STD		1
#define NOISE_QUALITY_BEST		2


// Billow //
#define DEFAULT_BILLOW_FREQUENCY		1.0
#define DEFAULT_BILLOW_LACUNARITY		2.0
#define DEFAULT_BILLOW_PERSISTENCE		0.5
#define DEFAULT_BILLOW_OCTAVE_COUNT		6
#define DEFAULT_BILLOW_SEED				0
#define BILLOW_MAX_OCTAVE				30
#define DEFAULT_BILLOW_QUALITY			NOISE_QUALITY_STD

real Billow (real3 point, real frequency, real lacunarity, real persistence, int noiseQuality, int octaveCount, int seed);


// Checkerboard //
real Checkerboard (real3 point);


// Curve //
real Curve (real3 point, real value, const real2 controlPoints[], int controlPointsCount);


// Cylinders //
#define DEFAULT_CYLINDERS_FREQUENCY		1.0

real Cylinders (real3 point, real frequency);


// Perlin //
#define DEFAULT_PERLIN_FREQUENCY		1.0
#define DEFAULT_PERLIN_LACUNARITY		2.0
#define DEFAULT_PERLIN_OCTAVE_COUNT		6
#define DEFAULT_PERLIN_PERSISTENCE		0.5
#define DEFAULT_PERLIN_QUALITY			NOISE_QUALITY_STD
#define DEFAULT_PERLIN_SEED				0
#define PERLIN_MAX_OCTAVE				30

real Perlin (real3 point, real frequency, real lacunarity, real persistence, int noiseQuality, int octaveCount, int seed);


// RidgedMulti //
#define DEFAULT_RIDGED_FREQUENCY		1.0
#define DEFAULT_RIDGED_LACUNARITY		2.0
#define DEFAULT_RIDGED_OCTAVE_COUNT		6
#define DEFAULT_RIDGED_QUALITY			NOISE_QUALITY_STD
#define DEFAULT_RIDGED_SEED				0
#define RIDGED_MAX_OCTAVE				30

real RidgedMulti (real3 point, real frequency, real lacunarity, int noiseQuality, int octaveCount, int seed, const real weights[30]);
void RidgedMulti_CalcSpectralWeights (real lacunarity, real weights[30]);


// Select //
#define DEFAULT_SELECT_EDGE_FALLOFF		 0.0
#define DEFAULT_SELECT_LOWER_BOUND		-1.0
#define DEFAULT_SELECT_UPPER_BOUND		 1.0

real Select (real3 point, real controlValue, real value0, real value1, real lowerBound, real upperBound, real edgeFalloff);


// Spheres //
#define DEFAULT_SPHERES_FREQUENCY		1.0
	
real Spheres (real3 point, real frequency);


// Terrace //
real Terrace (real3 point, const real controlPoints[], int controlPointsCount, real value, bool invertTerraces);


// Turbulence //
#define DEFAULT_TURBULENCE_FREQUENCY	DEFAULT_PERLIN_FREQUENCY
#define DEFAULT_TURBULENCE_POWER		1.0
#define DEFAULT_TURBULENCE_ROUGHNESS	3
#define DEFAULT_TURBULENCE_SEED			DEFAULT_PERLIN_SEED

real3 Turbulence (real3 vPoint, real power, real frequency, int roughness, int seed);


// Voronoi //
#define DEFAULT_VORONOI_DISPLACEMENT	1.0
#define DEFAULT_VORONOI_FREQUENCY		1.0
#define DEFAULT_VORONOI_SEED			0

real Voronoi (real3 point, real displacement, real frequency, int seed, bool enableDistance);



//------------------------------------------------------------------------------//
//									SOURCE										//

#define CubicMix(v0, v1, v2, v3, a) \
			((((v3) - (v2)) - ((v0) - (v1))) * a * a * a + \
			  ((v3) - (v2)) * a * a + \
			  ((v2) - (v0)) * a + \
			   (v1))
			   
constant real4	randomVectors[256] = {
	(real4)( -0.763874, -0.596439, -0.246489, 0.0 ),		(real4)( 0.396055, 0.904518, -0.158073, 0.0 ),
	(real4)( -0.499004, -0.8665, -0.0131631, 0.0 ),			(real4)( 0.468724, -0.824756, 0.316346, 0.0 ),
	(real4)( 0.829598, 0.43195, 0.353816, 0.0 ),			(real4)( -0.454473, 0.629497, -0.630228, 0.0 ),
	(real4)( -0.162349, -0.869962, -0.465628, 0.0 ),		(real4)( 0.932805, 0.253451, 0.256198, 0.0 ),
	(real4)( -0.345419, 0.927299, -0.144227, 0.0 ),			(real4)( -0.715026, -0.293698, -0.634413, 0.0 ),
	(real4)( -0.245997, 0.717467, -0.651711, 0.0 ),			(real4)( -0.967409, -0.250435, -0.037451, 0.0 ),
	(real4)( 0.901729, 0.397108, -0.170852, 0.0 ),			(real4)( 0.892657, -0.0720622, -0.444938, 0.0 ),
	(real4)( 0.0260084, -0.0361701, 0.999007, 0.0 ),		(real4)( 0.949107, -0.19486, 0.247439, 0.0 ),
	(real4)( 0.471803, -0.807064, -0.355036, 0.0 ),			(real4)( 0.879737, 0.141845, 0.453809, 0.0 ),
	(real4)( 0.570747, 0.696415, 0.435033, 0.0 ),			(real4)( -0.141751, -0.988233, -0.0574584, 0.0 ),
	(real4)( -0.58219, -0.0303005, 0.812488, 0.0 ),			(real4)( -0.60922, 0.239482, -0.755975, 0.0 ),
	(real4)( 0.299394, -0.197066, -0.933557, 0.0 ),			(real4)( -0.851615, -0.220702, -0.47544, 0.0 ),
	(real4)( 0.848886, 0.341829, -0.403169, 0.0 ),			(real4)( -0.156129, -0.687241, 0.709453, 0.0 ),
	(real4)( -0.665651, 0.626724, 0.405124, 0.0 ),			(real4)( 0.595914, -0.674582, 0.43569, 0.0 ),
	(real4)( 0.171025, -0.509292, 0.843428, 0.0 ),			(real4)( 0.78605, 0.536414, -0.307222, 0.0 ),
	(real4)( 0.18905, -0.791613, 0.581042, 0.0 ),			(real4)( -0.294916, 0.844994, 0.446105, 0.0 ),
	(real4)( 0.342031, -0.58736, -0.7335, 0.0 ),			(real4)( 0.57155, 0.7869, 0.232635, 0.0 ),
	(real4)( 0.885026, -0.408223, 0.223791, 0.0 ),			(real4)( -0.789518, 0.571645, 0.223347, 0.0 ),
	(real4)( 0.774571, 0.31566, 0.548087, 0.0 ),			(real4)( -0.79695, -0.0433603, -0.602487, 0.0 ),
	(real4)( -0.142425, -0.473249, -0.869339, 0.0 ),		(real4)( -0.0698838, 0.170442, 0.982886, 0.0 ),
	(real4)( 0.687815, -0.484748, 0.540306, 0.0 ),			(real4)( 0.543703, -0.534446, -0.647112, 0.0 ),
	(real4)( 0.97186, 0.184391, -0.146588, 0.0 ),			(real4)( 0.707084, 0.485713, -0.513921, 0.0 ),
	(real4)( 0.942302, 0.331945, 0.043348, 0.0 ),			(real4)( 0.499084, 0.599922, 0.625307, 0.0 ),
	(real4)( -0.289203, 0.211107, 0.9337, 0.0 ),			(real4)( 0.412433, -0.71667, -0.56239, 0.0 ),
	(real4)( 0.87721, -0.082816, 0.47291, 0.0 ),			(real4)( -0.420685, -0.214278, 0.881538, 0.0 ),
	(real4)( 0.752558, -0.0391579, 0.657361, 0.0 ),			(real4)( 0.0765725, -0.996789, 0.0234082, 0.0 ),
	(real4)( -0.544312, -0.309435, -0.779727, 0.0 ),		(real4)( -0.455358, -0.415572, 0.787368, 0.0 ),
	(real4)( -0.874586, 0.483746, 0.0330131, 0.0 ),			(real4)( 0.245172, -0.0838623, 0.965846, 0.0 ),
	(real4)( 0.382293, -0.432813, 0.81641, 0.0 ),			(real4)( -0.287735, -0.905514, 0.311853, 0.0 ),
	(real4)( -0.667704, 0.704955, -0.239186, 0.0 ),			(real4)( 0.717885, -0.464002, -0.518983, 0.0 ),
	(real4)( 0.976342, -0.214895, 0.0240053, 0.0 ),			(real4)( -0.0733096, -0.921136, 0.382276, 0.0 ),
	(real4)( -0.986284, 0.151224, -0.0661379, 0.0 ),		(real4)( -0.899319, -0.429671, 0.0812908, 0.0 ),
	(real4)( 0.652102, -0.724625, 0.222893, 0.0 ),			(real4)( 0.203761, 0.458023, -0.865272, 0.0 ),
	(real4)( -0.030396, 0.698724, -0.714745, 0.0 ),			(real4)( -0.460232, 0.839138, 0.289887, 0.0 ),
	(real4)( -0.0898602, 0.837894, 0.538386, 0.0 ),			(real4)( -0.731595, 0.0793784, 0.677102, 0.0 ),
	(real4)( -0.447236, -0.788397, 0.422386, 0.0 ),			(real4)( 0.186481, 0.645855, -0.740335, 0.0 ),
	(real4)( -0.259006, 0.935463, 0.240467, 0.0 ),			(real4)( 0.445839, 0.819655, -0.359712, 0.0 ),
	(real4)( 0.349962, 0.755022, -0.554499, 0.0 ),			(real4)( -0.997078, -0.0359577, 0.0673977, 0.0 ),
	(real4)( -0.431163, -0.147516, -0.890133, 0.0 ),		(real4)( 0.299648, -0.63914, 0.708316, 0.0 ),
	(real4)( 0.397043, 0.566526, -0.722084, 0.0 ),			(real4)( -0.502489, 0.438308, -0.745246, 0.0 ),
	(real4)( 0.0687235, 0.354097, 0.93268, 0.0 ),			(real4)( -0.0476651, -0.462597, 0.885286, 0.0 ),
	(real4)( -0.221934, 0.900739, -0.373383, 0.0 ),			(real4)( -0.956107, -0.225676, 0.186893, 0.0 ),
	(real4)( -0.187627, 0.391487, -0.900852, 0.0 ),			(real4)( -0.224209, -0.315405, 0.92209, 0.0 ),
	(real4)( -0.730807, -0.537068, 0.421283, 0.0 ),			(real4)( -0.0353135, -0.816748, 0.575913, 0.0 ),
	(real4)( 0.941391, 0.176991, -0.287153, 0.0 ),			(real4)( -0.154174, 0.390458, 0.90762, 0.0 ),
	(real4)( -0.283847, 0.533842, 0.796519, 0.0 ),			(real4)( -0.482737, -0.850448, 0.209052, 0.0 ),
	(real4)( -0.649175, 0.477748, 0.591886, 0.0 ),			(real4)( 0.885373, -0.405387, -0.227543, 0.0 ),
	(real4)( -0.147261, 0.181623, -0.972279, 0.0 ),			(real4)( 0.0959236, -0.115847, -0.988624, 0.0 ),
	(real4)( -0.89724, -0.191348, 0.397928, 0.0 ),			(real4)( 0.903553, -0.428461, -0.00350461, 0.0 ),
	(real4)( 0.849072, -0.295807, -0.437693, 0.0 ),			(real4)( 0.65551, 0.741754, -0.141804, 0.0 ),
	(real4)( 0.61598, -0.178669, 0.767232, 0.0 ),			(real4)( 0.0112967, 0.932256, -0.361623, 0.0 ),
	(real4)( -0.793031, 0.258012, 0.551845, 0.0 ),			(real4)( 0.421933, 0.454311, 0.784585, 0.0 ),
	(real4)( -0.319993, 0.0401618, -0.946568, 0.0 ),		(real4)( -0.81571, 0.551307, -0.175151, 0.0 ),
	(real4)( -0.377644, 0.00322313, 0.925945, 0.0 ),		(real4)( 0.129759, -0.666581, -0.734052, 0.0 ),
	(real4)( 0.601901, -0.654237, -0.457919, 0.0 ),			(real4)( -0.927463, -0.0343576, -0.372334, 0.0 ),
	(real4)( -0.438663, -0.868301, -0.231578, 0.0 ),		(real4)( -0.648845, -0.749138, -0.133387, 0.0 ),
	(real4)( 0.507393, -0.588294, 0.629653, 0.0 ),			(real4)( 0.726958, 0.623665, 0.287358, 0.0 ),
	(real4)( 0.411159, 0.367614, -0.834151, 0.0 ),			(real4)( 0.806333, 0.585117, -0.0864016, 0.0 ),
	(real4)( 0.263935, -0.880876, 0.392932, 0.0 ),			(real4)( 0.421546, -0.201336, 0.884174, 0.0 ),
	(real4)( -0.683198, -0.569557, -0.456996, 0.0 ),		(real4)( -0.117116, -0.0406654, -0.992285, 0.0 ),
	(real4)( -0.643679, -0.109196, -0.757465, 0.0 ),		(real4)( -0.561559, -0.62989, 0.536554, 0.0 ),
	(real4)( 0.0628422, 0.104677, -0.992519, 0.0 ),			(real4)( 0.480759, -0.2867, -0.828658, 0.0 ),
	(real4)( -0.228559, -0.228965, -0.946222, 0.0 ),		(real4)( -0.10194, -0.65706, -0.746914, 0.0 ),
	(real4)( 0.0689193, -0.678236, 0.731605, 0.0 ),			(real4)( 0.401019, -0.754026, 0.52022, 0.0 ),
	(real4)( -0.742141, 0.547083, -0.387203, 0.0 ),			(real4)( -0.00210603, -0.796417, -0.604745, 0.0 ),
	(real4)( 0.296725, -0.409909, -0.862513, 0.0 ),			(real4)( -0.260932, -0.798201, 0.542945, 0.0 ),
	(real4)( -0.641628, 0.742379, 0.192838, 0.0 ),			(real4)( -0.186009, -0.101514, 0.97729, 0.0 ),
	(real4)( 0.106711, -0.962067, 0.251079, 0.0 ),			(real4)( -0.743499, 0.30988, -0.592607, 0.0 ),
	(real4)( -0.795853, -0.605066, -0.0226607, 0.0 ),		(real4)( -0.828661, -0.419471, -0.370628, 0.0 ),
	(real4)( 0.0847218, -0.489815, -0.8677, 0.0 ),			(real4)( -0.381405, 0.788019, -0.483276, 0.0 ),
	(real4)( 0.282042, -0.953394, 0.107205, 0.0 ),			(real4)( 0.530774, 0.847413, 0.0130696, 0.0 ),
	(real4)( 0.0515397, 0.922524, 0.382484, 0.0 ),			(real4)( -0.631467, -0.709046, 0.313852, 0.0 ),
	(real4)( 0.688248, 0.517273, 0.508668, 0.0 ),			(real4)( 0.646689, -0.333782, -0.685845, 0.0 ),
	(real4)( -0.932528, -0.247532, -0.262906, 0.0 ),		(real4)( 0.630609, 0.68757, -0.359973, 0.0 ),
	(real4)( 0.577805, -0.394189, 0.714673, 0.0 ),			(real4)( -0.887833, -0.437301, -0.14325, 0.0 ),
	(real4)( 0.690982, 0.174003, 0.701617, 0.0 ),			(real4)( -0.866701, 0.0118182, 0.498689, 0.0 ),
	(real4)( -0.482876, 0.727143, 0.487949, 0.0 ),			(real4)( -0.577567, 0.682593, -0.447752, 0.0 ),
	(real4)( 0.373768, 0.0982991, 0.922299, 0.0 ),			(real4)( 0.170744, 0.964243, -0.202687, 0.0 ),
	(real4)( 0.993654, -0.035791, -0.106632, 0.0 ),			(real4)( 0.587065, 0.4143, -0.695493, 0.0 ),
	(real4)( -0.396509, 0.26509, -0.878924, 0.0 ),			(real4)( -0.0866853, 0.83553, -0.542563, 0.0 ),
	(real4)( 0.923193, 0.133398, -0.360443, 0.0 ),			(real4)( 0.00379108, -0.258618, 0.965972, 0.0 ),
	(real4)( 0.239144, 0.245154, -0.939526, 0.0 ),			(real4)( 0.758731, -0.555871, 0.33961, 0.0 ),
	(real4)( 0.295355, 0.309513, 0.903862, 0.0 ),			(real4)( 0.0531222, -0.91003, -0.411124, 0.0 ),
	(real4)( 0.270452, 0.0229439, -0.96246, 0.0 ),			(real4)( 0.563634, 0.0324352, 0.825387, 0.0 ),
	(real4)( 0.156326, 0.147392, 0.976646, 0.0 ),			(real4)( -0.0410141, 0.981824, 0.185309, 0.0 ),
	(real4)( -0.385562, -0.576343, -0.720535, 0.0 ),		(real4)( 0.388281, 0.904441, 0.176702, 0.0 ),
	(real4)( 0.945561, -0.192859, -0.262146, 0.0 ),			(real4)( 0.844504, 0.520193, 0.127325, 0.0 ),
	(real4)( 0.0330893, 0.999121, -0.0257505, 0.0 ),		(real4)( -0.592616, -0.482475, -0.644999, 0.0 ),
	(real4)( 0.539471, 0.631024, -0.557476, 0.0 ),			(real4)( 0.655851, -0.027319, -0.754396, 0.0 ),
	(real4)( 0.274465, 0.887659, 0.369772, 0.0 ),			(real4)( -0.123419, 0.975177, -0.183842, 0.0 ),
	(real4)( -0.223429, 0.708045, 0.66989, 0.0 ),			(real4)( -0.908654, 0.196302, 0.368528, 0.0 ),
	(real4)( -0.95759, -0.00863708, 0.288005, 0.0 ),		(real4)( 0.960535, 0.030592, 0.276472, 0.0 ),
	(real4)( -0.413146, 0.907537, 0.0754161, 0.0 ),			(real4)( -0.847992, 0.350849, -0.397259, 0.0 ),
	(real4)( 0.614736, 0.395841, 0.68221, 0.0 ),			(real4)( -0.503504, -0.666128, -0.550234, 0.0 ),
	(real4)( -0.268833, -0.738524, -0.618314, 0.0 ),		(real4)( 0.792737, -0.60001, -0.107502, 0.0 ),
	(real4)( -0.637582, 0.508144, -0.579032, 0.0 ),			(real4)( 0.750105, 0.282165, -0.598101, 0.0 ),
	(real4)( -0.351199, -0.392294, -0.850155, 0.0 ),		(real4)( 0.250126, -0.960993, -0.118025, 0.0 ),
	(real4)( -0.732341, 0.680909, -0.0063274, 0.0 ),		(real4)( -0.760674, -0.141009, 0.633634, 0.0 ),
	(real4)( 0.222823, -0.304012, 0.926243, 0.0 ),			(real4)( 0.209178, 0.505671, 0.836984, 0.0 ),
	(real4)( 0.757914, -0.56629, -0.323857, 0.0 ),			(real4)( -0.782926, -0.339196, 0.52151, 0.0 ),
	(real4)( -0.462952, 0.585565, 0.665424, 0.0 ),			(real4)( 0.61879, 0.194119, -0.761194, 0.0 ),
	(real4)( 0.741388, -0.276743, 0.611357, 0.0 ),			(real4)( 0.707571, 0.702621, 0.0752872, 0.0 ),
	(real4)( 0.156562, 0.819977, 0.550569, 0.0 ),			(real4)( -0.793606, 0.440216, 0.42, 0.0 ),
	(real4)( 0.234547, 0.885309, -0.401517, 0.0 ),			(real4)( 0.132598, 0.80115, -0.58359, 0.0 ),
	(real4)( -0.377899, -0.639179, 0.669808, 0.0 ),			(real4)( -0.865993, -0.396465, 0.304748, 0.0 ),
	(real4)( -0.624815, -0.44283, 0.643046, 0.0 ),			(real4)( -0.485705, 0.825614, -0.287146, 0.0 ),
	(real4)( -0.971788, 0.175535, 0.157529, 0.0 ),			(real4)( -0.456027, 0.392629, 0.798675, 0.0 ),
	(real4)( -0.0104443, 0.521623, -0.853112, 0.0 ),		(real4)( -0.660575, -0.74519, 0.091282, 0.0 ),
	(real4)( -0.0157698, -0.307475, -0.951425, 0.0 ),		(real4)( -0.603467, -0.250192, 0.757121, 0.0 ),
	(real4)( 0.506876, 0.25006, 0.824952, 0.0 ),			(real4)( 0.255404, 0.966794, 0.00884498, 0.0 ),
	(real4)( 0.466764, -0.874228, -0.133625, 0.0 ),			(real4)( 0.475077, -0.0682351, -0.877295, 0.0 ),
	(real4)( -0.224967, -0.938972, -0.260233, 0.0 ),		(real4)( -0.377929, -0.814757, -0.439705, 0.0 ),
	(real4)( -0.305847, 0.542333, -0.782517, 0.0 ),			(real4)( 0.26658, -0.902905, -0.337191, 0.0 ),
	(real4)( 0.0275773, 0.322158, -0.946284, 0.0 ),			(real4)( 0.0185422, 0.716349, 0.697496, 0.0 ),
	(real4)( -0.20483, 0.978416, 0.0273371, 0.0 ),			(real4)( -0.898276, 0.373969, 0.230752, 0.0 ),
	(real4)( -0.00909378, 0.546594, 0.837349, 0.0 ),		(real4)( 0.6602, -0.751089, 0.000959236, 0.0 ),
	(real4)( 0.855301, -0.303056, 0.420259, 0.0 ),			(real4)( 0.797138, 0.0623013, -0.600574, 0.0 ),
	(real4)( 0.48947, -0.866813, 0.0951509, 0.0 ),			(real4)( 0.251142, 0.674531, 0.694216, 0.0 ),
	(real4)( -0.578422, -0.737373, -0.348867, 0.0 ),		(real4)( -0.254689, -0.514807, 0.818601, 0.0 ),
	(real4)( 0.374972, 0.761612, 0.528529, 0.0 ),			(real4)( 0.640303, -0.734271, -0.225517, 0.0 ),
	(real4)( -0.638076, 0.285527, 0.715075, 0.0 ),			(real4)( 0.772956, -0.15984, -0.613995, 0.0 ),
	(real4)( 0.798217, -0.590628, 0.118356, 0.0 ),			(real4)( -0.986276, -0.0578337, -0.154644, 0.0 ),
	(real4)( -0.312988, -0.94549, 0.0899272, 0.0 ),			(real4)( -0.497338, 0.178325, 0.849032, 0.0 ),
	(real4)( -0.101136, -0.981014, 0.165477, 0.0 ),			(real4)( -0.521688, 0.0553434, -0.851339, 0.0 ),
	(real4)( -0.786182, -0.583814, 0.202678, 0.0 ),			(real4)( -0.565191, 0.821858, -0.0714658, 0.0 ),
	(real4)( 0.437895, 0.152598, -0.885981, 0.0 ),			(real4)( -0.92394, 0.353436, -0.14635, 0.0 ),
	(real4)( 0.212189, -0.815162, -0.538969, 0.0 ),			(real4)( -0.859262, 0.143405, -0.491024, 0.0 ),
	(real4)( 0.991353, 0.112814, 0.0670273, 0.0 ),			(real4)( 0.0337884, -0.979891, -0.196654, 0.0 )
};

constant int X_NOISE_GEN		= 1619;
constant int Y_NOISE_GEN		= 31337;
constant int Z_NOISE_GEN		= 6971;
constant int SEED_NOISE_GEN		= 1013;
constant int SHIFT_NOISE_GEN	= 8;

#define MakeInt32Range(n)\
	( (n) >= (real)(1073741824.0) ? (( (real)(2.0) * fmod( (n), (real)(1073741824.0) ) ) - (real)(1073741824.0))\
		: (((n) <= -(real)(1073741824.0)) ? (( (real)(2.0) * fmod( (n), (real)(1073741824.0) ) ) + (real)(1073741824.0))\
		: (n) ))

#define SCurve3(a)						((a) * (a) * ((real)(3.0) - (real)(2.0) * (a)))

#define ValueNoise3DV3(p, seed)			((real)(1.0) - ( (real)IntValueNoise3D( (p), (seed) ) / (real)(1073741824.0) ))
#define ValueNoise3D(x, y, z, seed)		ValueNoise3DV3( (int3)( (x), (y), (z) ), (seed) )

#define GradientNoise3D(f, ix, iy, iz, seed)	GradientNoise3DV3( (f), (int3)((ix), (iy), (iz)), (seed) )

real3 MakeInt32RangeV3(real3 n)
{
	return (real3)( MakeInt32Range( n.x ), MakeInt32Range( n.y ), MakeInt32Range( n.z ) );
}

real3 SCurve3V3(real3 a)
{
	return (real3)( SCurve3( a.x ), SCurve3( a.y ), SCurve3( a.z ) );
}

real SCurve5 (real a)
{
	real a3 = a * a * a;
	real a4 = a3 * a;
	real a5 = a4 * a;
	return ((real)(6.0) * a5) - ((real)(15.0) * a4) + ((real)(10.0) * a3);
}

real3 SCurve5V3(real3 a)
{
	return (real3)( SCurve5( a.x ), SCurve5( a.y ), SCurve5( a.z ) );
}

int IntValueNoise3D (int3 p, int seed)
{
	int n	= ( X_NOISE_GEN    * p.x +
				Y_NOISE_GEN    * p.y +
				Z_NOISE_GEN    * p.z +
				SEED_NOISE_GEN * seed) & 0x7fffffff;
	n = (n >> 13) ^ n;
	return (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
}

real GradientNoise3DV3 (real3 f, int3 i, int seed)
{
	int vectorIndex = ( X_NOISE_GEN    * i.x +
						Y_NOISE_GEN    * i.y +
						Z_NOISE_GEN    * i.z +
						SEED_NOISE_GEN * seed) & 0xffffffff;
	vectorIndex ^= (vectorIndex >> SHIFT_NOISE_GEN);
	vectorIndex &= 0xff;
	real3 gradient	= randomVectors[vectorIndex].xyz;
	real3 point		= f - convert_real3(i);
	return dot( gradient, point ) * (real)(2.12);
}

real GradientCoherentNoise3D (real3 p, int seed, int noiseQuality)
{
	int3	p0 = (int3)( p.x > 0.0 ? (int)p.x : (int)p.x - 1,
							p.y > 0.0 ? (int)p.y : (int)p.y - 1,
							p.z > 0.0 ? (int)p.z : (int)p.z - 1 );
	int3	p1 = p0 + 1;
	real3	s;
			
	switch (noiseQuality)
	{
		case NOISE_QUALITY_FAST :	s = p - convert_real3(p0);				break;
		case NOISE_QUALITY_STD  :	s = SCurve3V3( p - convert_real3(p0) );	break;
		case NOISE_QUALITY_BEST :	s = SCurve5V3( p - convert_real3(p0) );	break;
	}
	real2	n,
			i0,
			i1;
			
	n.x  = GradientNoise3D( p, p0.x, p0.y, p0.z, seed );
	n.y  = GradientNoise3D( p, p1.x, p0.y, p0.z, seed );
	i0.x = mix( n.x, n.y, s.x );
	n.x  = GradientNoise3D( p, p0.x, p1.y, p0.z, seed );
	n.y  = GradientNoise3D( p, p1.x, p1.y, p0.z, seed );
	i1.x = mix( n.x, n.y, s.x );
	i0.y = mix( i0.x, i1.x, s.y );
	n.x  = GradientNoise3D( p, p0.x, p0.y, p1.z, seed );
	n.y  = GradientNoise3D( p, p1.x, p0.y, p1.z, seed );
	i0.x = mix( n.x, n.y, s.x );
	n.x  = GradientNoise3D( p, p0.x, p1.y, p1.z, seed );
	n.y  = GradientNoise3D( p, p1.x, p1.y, p1.z, seed );
	i1.x = mix( n.x, n.y, s.x );
	i1.y = mix( i0.x, i1.x, s.y );
	return mix( i0.y, i1.y, s.z );
}

real ValueCoherentNoise3D (real3 p, int seed, int noiseQuality)
{
	int3	p0 = (int3)( p.x > 0.0 ? (int)p.x : (int)p.x - 1,
							p.y > 0.0 ? (int)p.y : (int)p.y - 1,
							p.z > 0.0 ? (int)p.z : (int)p.z - 1 );
	int3	p1 = p0 + 1;
	real3	s;
			
	switch (noiseQuality)
	{
		case 0 :	s = p - convert_real3(p0);				break;
		case 1 :	s = SCurve3V3( p - convert_real3(p0) );	break;
		case 2 :	s = SCurve5V3( p - convert_real3(p0) );	break;
	}
			
	real2	n,
			i0,
			i1;
			
	n.x  = ValueNoise3DV3( p0, seed );
	n.y  = ValueNoise3D( p1.x, p0.y, p0.z, seed );
	i0.x = mix( n.x, n.y, s.x );
	n.x  = ValueNoise3D( p0.x, p1.x, p0.z, seed);
	n.y  = ValueNoise3D( p1.x, p1.y, p0.z, seed );
	i1.x = mix( n.x, n.y, s.x );
	i0.x = mix( i0.x, i1.x, s.y );
	n.x  = ValueNoise3D( p0.x, p0.y, p1.z, seed );
	n.y  = ValueNoise3D( p1.x, p0.x, p1.z, seed );
	i0.x = mix( n.x, n.y, s.x );
	n.x  = ValueNoise3D( p0.x, p1.y, p1.z, seed );
	n.y  = ValueNoise3D( p1.x, p1.y, p1.z, seed );
	i1.x = mix( n.x, n.y, s.x );
	i1.y = mix( i0.x, i1.x, s.y );
	return mix( i0.y, i1.y, s.z );
}

real Billow (real3 vPoint, real _frequency, real _lacunarity, real _persistence,
				int _noiseQuality, int _octaveCount, int _seed)
{
	real	value		= 0.0;
	real	signal		= 0.0;
	real	persistence	= 1.0;
	real3	p			= vPoint * _frequency;
	real3	n;
	int		seed;
	
	for (int octave = 0; octave < _octaveCount; ++octave)
	{
		n = MakeInt32RangeV3( p );
		
		seed = (_seed + octave) & 0xffffffff;
		signal = GradientCoherentNoise3D( n, seed, _noiseQuality );
		signal = (real)(2.0) * fabs(signal) - (real)(1.0);
		value += signal * persistence;
		
		p *= _lacunarity;
		persistence *= _persistence;
	}
	value += (real)(0.5);
	return value;
}

real Checkerboard (real3 vPoint)
{
	int ix = (int)( floor( MakeInt32Range(vPoint.x) ) );
	int iy = (int)( floor( MakeInt32Range(vPoint.y) ) );
	int iz = (int)( floor( MakeInt32Range(vPoint.z) ) );
	return (real)( (ix & 1 ^ iy & 1 ^ iz & 1) != 0 ? -1.0 : 1.0 );
}

real Curve (real3 vPoint, real value, const real2 controlPoints[], int controlPointsCount)
{
	int indexPos = 0;
	for (; indexPos < controlPointsCount; ++indexPos) {
		if ( value < controlPoints[indexPos].x )
			break;
	}
	
	int index0 = clamp( indexPos - 2, 0, controlPointsCount - 1 );
	int index1 = clamp( indexPos - 1, 0, controlPointsCount - 1 );
	int index2 = clamp( indexPos    , 0, controlPointsCount - 1 );
	int index3 = clamp( indexPos + 1, 0, controlPointsCount - 1 );
	
	if ( index1 == index2 ) {
		return controlPoints[index1].y;
	}
		
	real input0 = controlPoints[index1].x;
	real input1 = controlPoints[index2].x;
	real alpha  = (value - input0) / (input1 - input0);
	
	return CubicMix( controlPoints[index0].y, controlPoints[index1].y,
						controlPoints[index2].y, controlPoints[index3].y, alpha );
}

real Cylinders (real3 vPoint, real _frequency)
{
	real x = vPoint.x * _frequency;
	real z = vPoint.z * _frequency;
	real distFromCenter = sqrt( x * x + z * z );
	real distFromSmallerSphere = distFromCenter - floor( distFromCenter );
	real distFromLargerSphere = (real)(1.0) - distFromSmallerSphere;
	real nearestDist = min( distFromSmallerSphere, distFromLargerSphere );
	return (real)(1.0) - ( nearestDist * (real)(4.0) );
}

real Perlin (real3 vPoint, real _frequency, real _lacunarity, real _persistence,
				int _noiseQuality, int _octaveCount, int _seed)
{
	real value = 0.0;
	real signal = 0.0;
	real persistence = 1.0;
	int seed;
	real3 n;
	real3 p = vPoint * _frequency;
	
	for (int octave = 0; octave < _octaveCount; octave++)
	{
		n = MakeInt32RangeV3( p );
		seed = (_seed + octave) & 0xffffffff;
		signal = GradientCoherentNoise3D( n, seed, _noiseQuality );
		value += signal * persistence;
		p *= _lacunarity;
		persistence *= _persistence;
	}
	return value;
}

void RidgedMulti_CalcSpectralWeights (real lacunarity, real weights[30])
{
	real	h	 = 1.0;
	real	freq = 1.0;
	
	for (int i = 0; i < 30; ++i)
	{
		weights[i] = pow( freq, -h );
		freq *= lacunarity;
	}
}

real RidgedMulti (real3 vPoint, real _frequency, real _lacunarity,
					int _noiseQuality, int _octaveCount, int _seed,
					const real weights[30])
{
	real3 p		= vPoint * _frequency;
	real signal = 0.0;
	real value  = 0.0;
	real weight = 1.0;
	real offset = 1.0;
	real gain	= 2.0;
	
	for (int octave = 0; octave < _octaveCount; octave++)
	{
		real3 n = MakeInt32RangeV3( p );
		
		int seed = (_seed + octave) & 0x7fffffff;
		signal = GradientCoherentNoise3D( n, seed, _noiseQuality );
		
		signal = fabs( signal );
		signal = offset - signal;
		signal *= signal;
		signal *= weight;
		weight = signal * gain;
		
		if ( weight > 1.0 )	weight = 1.0;
		if ( weight < 0.0 )	weight = 0.0;
		
		value += (signal * weights[octave]);
		
		p *= _lacunarity;
	}
	
	return (value * (real)(1.25)) - (real)(1.0);
}

real Select (real3 vPoint, real controlValue, real value0, real value1,
				real _lowerBound, real _upperBound, real _edgeFalloff)
{
	real alpha;
						
	if ( _edgeFalloff > 0.0 )
	{
		if ( controlValue < (_lowerBound - _edgeFalloff) ) {
			return value0;
		} else
		if ( controlValue < (_lowerBound + _edgeFalloff) )
		{
			real lowerCurve = (_lowerBound - _edgeFalloff);
			real upperCurve = (_lowerBound + _edgeFalloff);
			alpha = SCurve3( (controlValue - lowerCurve) / (upperCurve - lowerCurve) );
			return mix( value0, value0, alpha );
		}
		else
		if ( controlValue < (_upperBound - _edgeFalloff) )
			return value1;
		else
		if ( controlValue < (_upperBound + _edgeFalloff) ) {
			real lowerCurve = (_upperBound - _edgeFalloff);
			real upperCurve = (_upperBound + _edgeFalloff);
			alpha = SCurve3 ( (controlValue - lowerCurve) / (upperCurve - lowerCurve) );
			return mix( value1, value0, alpha );
		}
		else
			return value0;
	}
	else
	{
		if ( controlValue < _lowerBound or controlValue > _upperBound )
			return value0;
		else
			return value1;
	}
}

real Spheres (real3 vPoint, real _frequency)
{
	real3 p = vPoint * _frequency;
	real distFromCenter = length(p);
	real distFromSmallerSphere = distFromCenter - floor( distFromCenter );
	real distFromLargerSphere = (real)(1.0) - distFromSmallerSphere;
	real nearestDist = min( distFromSmallerSphere, distFromLargerSphere );
	return (real)(1.0) - ( nearestDist * (real)(4.0) );
}

real Terrace (real3 vPoint, const real controlPoints[],
				int controlPointsCount, real value, bool invertTerraces)
{
	int indexPos;
	for (indexPos = 0; indexPos < controlPointsCount; ++indexPos) {
		if (value < controlPoints[indexPos]) {
			break;
		}
	}
	
	int index0 = clamp( indexPos - 1, 0, controlPointsCount - 1 );
	int index1 = clamp( indexPos    , 0, controlPointsCount - 1 );
	
	if ( index0 == index1 ) {
		return controlPoints[index1];
	}
	
	real value0 = controlPoints[index0];
	real value1 = controlPoints[index1];
	real alpha  = (value - value0) / (value1 - value0);
	
	if ( invertTerraces )
	{
		alpha = (real)(1.0) - alpha;
		real tmp = value0;
		value0 = value1;
		value1 = tmp;
	}
	
	alpha *= alpha;
	return mix( value0, value1, alpha );
}

real3 Turbulence (real3 vPoint, real power, real frequency, int roughness, int seed)
{
	real3 p0 = vPoint + (real3)( 12414.0, 65124.0, 31337.0 ) / 65536.0;
	real3 p1 = vPoint + (real3)( 26519.0, 18128.0, 60493.0 ) / 65536.0;
	real3 p2 = vPoint + (real3)( 53820.0, 11213.0, 44845.0 ) / 65536.0;
	
	real lacunarity = DEFAULT_PERLIN_LACUNARITY;
	real persistence = DEFAULT_PERLIN_PERSISTENCE;
	int noiseQuality = DEFAULT_PERLIN_QUALITY;

	real3 distort = (real3)( Perlin( p0, frequency, lacunarity, persistence, noiseQuality, roughness, seed ),
							 Perlin( p1, frequency, lacunarity, persistence, noiseQuality, roughness, seed ),
							 Perlin( p2, frequency, lacunarity, persistence, noiseQuality, roughness, seed ) )
							 * power + vPoint;
		
	return distort;
}

real Voronoi (real3 vPoint, real _displacement, real _frequency, int _seed, bool _enableDistance)
{
	real3 p		= vPoint * _frequency;
	int3  init	= (int3)( vPoint.x > 0.0 ? (int)(vPoint.x) : (int)(vPoint.x) - 1,
						  vPoint.y > 0.0 ? (int)(vPoint.y) : (int)(vPoint.y) - 1,
						  vPoint.z > 0.0 ? (int)(vPoint.z) : (int)(vPoint.z) - 1 );
	int3  cur	= (int3)(0);
	
	real minDist = (real)(2147483647.0);
	real3 candidate = (real3)(0);
	
	for (cur.z = init.z - 2; cur.z <= init.z + 2; ++cur.z)
	{
		for (cur.y = init.y - 2; cur.y <= init.y + 2; ++cur.y)
		{
			for (cur.x = init.x - 2; cur.x <= init.x + 2; ++cur.x)
			{
				real3 pos		= (real3)(	ValueNoise3DV3( cur, _seed ),
											ValueNoise3DV3( cur, _seed + 1 ),
											ValueNoise3DV3( cur, _seed + 2 ) ) + convert_real3(cur);
				
				real3 distVec	= pos - vPoint;
				real  dist		= dot( distVec, distVec );
				
				if ( dist < minDist )
				{
					minDist = dist;
					candidate = pos;
				}
			}
		}
	}
	
	const real SQRT_3 = (real)(1.73205080756887729352);
	
	real value;
	if ( _enableDistance )
	{
		real3 distVec = candidate - vPoint;
		value = length(distVec) * SQRT_3 - (real)(1.0);
	}
	else
		value = 0.0;
	
	return value + (_displacement * ValueNoise3DV3( convert_int3(floor(candidate)), 0 ) );
}
